package com.yhq.spring.manual;

import lombok.SneakyThrows;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;

import java.beans.Introspector;

/**
 * @author hqyin
 * @date 2023/4/6 5:12 下午
 */
public class YhqContext extends MyBeanFactory{
    public <T> YhqContext(Class<T> configClass) {
        refresh(configClass);
    }

    private <T> void refresh(Class<T> configClass) {
        invokeBeanFactoryPostProcessor(configClass);

        preInstantiateSingletons();
    }

    private void preInstantiateSingletons() {
        this.beanDefinitionMap.forEach((beanName, beanDefinition) -> {
            //单例非懒加载，则初始化单例对象
            if(beanDefinition.isSingleton() && !beanDefinition.isLazyInit()) {
                getBean(beanName);
            }
        });
    }

    private <T> void invokeBeanFactoryPostProcessor(Class<T> configClass) {
        if(configClass.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScan =  configClass.getAnnotation(ComponentScan.class);
            String packagePath = componentScan.value()[0].replace(".","/");
            doScan(packagePath);
        }
    }

    @SneakyThrows
    private void doScan(String... packagePath) {
        //先扫描
        String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                packagePath[0] + '/' + "**/*.class";
        Resource[] resources = new PathMatchingResourcePatternResolver().getResources(packageSearchPath);
        for (Resource resource : resources) {
            //再读取
            MetadataReader metadataReader = new CachingMetadataReaderFactory().getMetadataReader(resource);
            Class originalClass = Class.forName(metadataReader.getAnnotationMetadata().getClassName());
            if(originalClass.isAnnotationPresent(Component.class)) {
                CustomBeanDefinition bd= new CustomBeanDefinition();
                bd.setType(metadataReader.getAnnotationMetadata().getClassName());
                //设置scope
                if(originalClass.isAnnotationPresent(Scope.class)) {
                    Scope scope = (Scope) originalClass.getAnnotation(Scope.class);
                    bd.setScope(scope.value());
                }
                //设置是否懒加载
                if(originalClass.isAnnotationPresent(Lazy.class)){
                    bd.setLazyInit(true);
                }

                //再注册
                String shortClassName = ClassUtils.getShortName(bd.getType());
                String beanName = Introspector.decapitalize(shortClassName);
                beanDefinitionMap.put(beanName,bd);
            }
        }
    }
}
